// Promise

// 可信任的promise
// Promise.resolve(..) 创建一个已经完成的Promise
// 接收一个非Promise，非thenable的立即值，返回一个用这个值填充的promise
// 接收一个真正的promise，只会返回同一个promise
var p1 = new Promise(function (resolve, reject) {
  resolve(42);
});
var p2 = Promise.resolve(42);
var p3 = Promise.resolve(p2);
console.log(p2 === p3);

var p = {
  then: function (cb, errcb) {
    cb(42);
    errcb("evil laugh");
  },
};
p.then(
  function fulfilled(val) {
    console.log(val);
  },
  function rejected(err) {
    console.log(err);
  }
);
// 向Promise.resolve(..) 传递一个非Promise的thenable值，会展开这个值，持续到提取出一个具体的非类Promise的最终值
Promise.resolve(p).then(
  function fulfilled(val) {
    console.log(val);
  },
  function rejected(err) {
    // 永远不会到达这里
    console.log(err);
  }
);

// 链式流 把多个Promise连接到一起以表示一系列异步步骤
// 依赖于Promise的两个固有行为特性
// 1.调用then 会返回一个新的Promise，可以将其连接起来
// 2.then(..)调用的完成回调（第一个参数）的返回值，被自动设置成被链接Promise的完成

// Promise API 概述
// new Promise(..) 构造器
// 必须和new一起使用，必须提供一个函数回调，这个回调是同步或立即调用的
// 这个函数接收两个函数回调，用以支持promise的决议，通常为 resoleve() reject()
var pro = new Promise(function (resolve, reject) {
  resolve(); // 决议/完成这个promise 若传给resolve的是 非promise 非thenable的立即值，这个promise就用这个值完成
  reject(); // 拒绝这个promise
});

// Promise.reject(..) 创建一个已拒绝的Promise
// p3 p4等价
var p3 = new Promise(function (resolve, reject) {
  reject("oops");
}).catch(function (err) {});
var p4 = Promise.reject("oops").catch(function (err) {});

// 每个Promise都有then和catch方法，这两方法可以为这个promise注册完成和拒绝处理函数
// then(..)接收一个或两个参数，第一个用于完成回调，第二个用于拒绝回调，若俩个中任何一个被省略或者作为非函数值传入的话，就会替换为对应的默认回调
// catch(..)只接收一个拒绝回调做参数，并自动替换默认完成回调，等价于 then(null, ..)
// then 和 catch会创建并返回新的promise

// Promise.all([..]) Promise.race([..]) 都会创建一个Promise作为他们的返回值
// Promise.all([..]) 传入的所有promise都完成，返回的promise才完成（得到一个所有promise的完成值的数组），若有一个promise被拒绝，主promise就会立即被拒绝
// Promise.race([..]) 第一个决议的promise取胜，决议结果成为主promise的决议
// all传入空数组会立即完成，race传入空数组会挂住，永不决议

var a1 = Promise.resolve(42);
var a2 = Promise.resolve("hello world");
var a3 = Promise.reject("oops");

Promise.race([a1, a2, a3]).then(function (msg) {
  console.log(msg);
});

Promise.all([a1, a2, a3]).catch(function (err) {
  console.log(err);
});

Promise.all([a1, a2]).then(function aa(msg) {
  console.log(msg);
});


// Promise局限性
// 顺序错误处理

// 单一值 Promise只能有一个完成值或一个拒绝理由。复杂场景中会局限

// 无法取消

